package com.hbnu.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbnu.system.config.BaseException;
import com.hbnu.system.constant.RoleConstant;
import com.hbnu.system.constant.StatusCheckConstant;
import com.hbnu.system.core.base.CommonPage;
import com.hbnu.system.core.service.IBeanService;
import com.hbnu.system.core.util.PageUtil;
import com.hbnu.system.model.context.BaseContext;
import com.hbnu.system.model.entity.*;
import com.hbnu.system.mapper.PatentMapper;
import com.hbnu.system.model.dto.*;
import com.hbnu.system.model.query.PatentPageQuery;
import com.hbnu.system.model.vo.InfoVO;
import com.hbnu.system.model.vo.PatentVO;
import com.hbnu.system.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbnu.system.utils.CheckAuditHelper;
import com.hbnu.system.utils.CheckRoleUtil;
import com.hbnu.system.utils.JwtUtils;
import com.hbnu.system.utils.UserInfoUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2023-05-16
 */
@Service
public class PatentServiceImpl extends ServiceImpl<PatentMapper, Patent> implements IPatentService {

    @Autowired
    private IUserService iUserService;

    @Autowired
    private IDeptService iDeptService;

    @Autowired
    private IdToStatsService idToStatsService;

    @Autowired
    private PatentfileService patentfileService;

    @Autowired
    private IAuthorityService iAuthorityService;

    @Autowired
    private AuditService auditService;

    @Autowired
    private PatentMapper patentMapper;

    @Autowired
    private IPatentauthorService iPatentauthorService;

    @Autowired
    private IPatentQualificationSerivce iPatentQualificationSerivce;

    @Autowired
    private CheckRoleUtil checkRoleUtil;

    @Autowired
    private CheckAuditHelper checkAuditHelper ;

    @Autowired
    private UserInfoUtils userInfoUtils;
    /**
     * 添加专利
     * @param
     * @return
     */
    @Override
    public boolean addPatent(@RequestBody PatentDTO patentdto) {
        if(StrUtil.isEmpty(patentdto.getPatentCate()) || StrUtil.isBlank(patentdto.getPatentCate())){
            throw new BaseException("请输入专利类型");
        }
        if(StrUtil.isEmpty(patentdto.getEntered()) || StrUtil.isBlank(patentdto.getEntered())){
            throw new BaseException("请输入录入人");
        }

        if(StrUtil.isEmpty(patentdto.getPatentName()) || StrUtil.isBlank(patentdto.getPatentName())){
            throw new BaseException("请输入专利名称");
        }
        if(Objects.nonNull(super.getOne(Wrappers.lambdaQuery(Patent.class)
                .eq(Patent::getPatentName,patentdto.getPatentName())))){
            throw new BaseException("专利名称重复!");
        }
        if(StrUtil.isEmpty(patentdto.getPatentNumber()) || StrUtil.isBlank(patentdto.getPatentNumber())){
            throw new BaseException("请输入专利号");
        }
        if(StrUtil.isEmpty(patentdto.getPatentee()) || StrUtil.isBlank(patentdto.getPatentee())){
            throw new BaseException("请输入专利权人");
        }
        if(StrUtil.isEmpty(patentdto.getDept()) || StrUtil.isBlank(patentdto.getDept())){
            throw new BaseException("请输入所属机构");
        }else{
            // 根据dept ID获取对应的deptName
            Dept dept = iDeptService.getOne(Wrappers.lambdaQuery(Dept.class)
                    .eq(Dept::getDeptID, patentdto.getDept()));
            if (dept == null) {
                throw new BaseException("所属机构不存在");
            }
            patentdto.setDeptName(dept.getDeptName()); // 假设Dept实体类中name字段存储机构名称
        }
        patentdto.setStatus("草稿");
        if (StrUtil.isEmpty(patentdto.getLeadAuthor()) || StrUtil.isBlank(patentdto.getLeadAuthor())){
            patentdto.setLeadAuthor("");
        }
        if (StrUtil.isEmpty(patentdto.getCorrespondingAuthor()) || StrUtil.isBlank(patentdto.getCorrespondingAuthor())){
            patentdto.setCorrespondingAuthor("");
        }
        patentdto.setEnteredDate(LocalDateTime.now());
        Patent patent = new Patent();
        BeanUtils.copyProperties(patentdto,patent);
        return baseMapper.insert(patent) == 1;
    }

    /**
     * 删除专利
     * @param patentID
     * @return
     */
    @Override
    public boolean deletePatent(String patentID) throws IOException {
        Patent patent = super.getOne(Wrappers.lambdaQuery(Patent.class)
                .eq(Patent::getPatentID, patentID));
        //校验普通用户权限不能修改当前状态信息
        checkRoleUtil.checkPermissionAchievement(patent.getStatus());

        // 删除专利关联的作者根据专利id
        iPatentauthorService.remove(Wrappers.lambdaQuery(Patentauthor.class)
                .eq(Patentauthor::getPatentID, patentID));

        // 删除专利关联的文件信息根据专利id
        patentfileService.remove(Wrappers.lambdaQuery(Patentfile.class)
                .eq(Patentfile::getPatentid, patentID));

        //删除专利关联的量化分数根据论文id
        iPatentQualificationSerivce.remove(Wrappers.lambdaQuery(Patent_Qualification.class)
                .eq(Patent_Qualification::getPatentID, patentID));

        // 删除专利关联的文件信息
        // 1. 根据专利ID查询出所有的文件信息ID
        List<Patentfile> patentFiles = patentfileService.list(Wrappers.lambdaQuery(Patentfile.class)
                .eq(Patentfile::getPatentid, patentID));
        // 2. 拿到ID集合
        List<String> fileIds = patentFiles.stream()
                .map(Patentfile::getFileid)
                .collect(Collectors.toList());
        // 3. 删除文件
        for (String fileId : fileIds) {
            patentfileService.deletPatentfile(fileId);
        }

        // 删除审核记录根据专利ID
        auditService.remove(Wrappers.lambdaQuery(Audit.class)
                .eq(Audit::getSynthesisID, patentID));

        // 最后删除专利本身
        return baseMapper.deleteById(patentID) == 1;

    }

    /**
     * 修改专利信息
     * @param patent
     * @return
     */
    @Override
    public boolean updatePatent(Patent patent) {
        //校验普通用户权限不能修改当前状态信息
        checkRoleUtil.checkPermissionAchievement(patent.getStatus());


        if(StrUtil.isEmpty(patent.getPatentCate()) || StrUtil.isBlank(patent.getPatentCate())){
            throw new BaseException("请输入专利类型");
        }
        if(StrUtil.isEmpty(patent.getEntered()) || StrUtil.isBlank(patent.getEntered())){
            throw new BaseException("请输入录入人");
        }
        if(StrUtil.isEmpty(patent.getPatentName()) || StrUtil.isBlank(patent.getPatentName())){
            throw new BaseException("请输入专利名称");
        }
        if(StrUtil.isEmpty(patent.getPatentNumber()) || StrUtil.isBlank(patent.getPatentNumber())){
            throw new BaseException("请输入专利号");
        }
        if(StrUtil.isEmpty(patent.getPatentee()) || StrUtil.isBlank(patent.getPatentee())){
            throw new BaseException("请输入专利权人");
        }

        //判断该专利名是否被使用
        Patent one = super.getOne(Wrappers.lambdaQuery(Patent.class)
                .eq(Patent::getPatentName, patent.getPatentName())
                .ne(Patent::getPatentID, patent.getPatentID()));
        if (Objects.nonNull(one)) {
            throw new BaseException("该专利名称已被使用");
        }

        return baseMapper.updateById(patent) == 1;

    }

    /**
     * 根据专利ID查询专利
     * @param patentID
     * @return
     */
    @Override
    public PatentDTO getPatentDTOById(String patentID) {
        Patent patent = super.getOne(Wrappers.lambdaQuery(Patent.class)
                .eq(Patent::getPatentID, patentID));
        if(Objects.isNull(patent)){
            throw new BaseException("专利编号异常!");
        }
        String entered = idToStatsService.IdToName(patent.getEntered());
        String dept=idToStatsService.IdToDept(patent.getDept());
        String allauthor=idToStatsService.IdToAllauthor(patent.getAllAuthor());

        PatentDTO patentdto = new PatentDTO();
        BeanUtils.copyProperties(patent,patentdto);

        patentdto.setAllAuthorName(allauthor);
        patentdto.setEnteredName(entered);
        patentdto.setDeptName(dept);

        return patentdto;
    }

    /**
     * 后端自己使用
     * @param patentID
     * @return
     */
    @Override
    public Patent getPatentById(String patentID) {
        Patent patent = super.getOne(Wrappers.lambdaQuery(Patent.class)
                .eq(Patent::getPatentID, patentID));
        if(Objects.isNull(patent)){
            throw new BaseException("专利编号异常!未查找到该专利");
        }
        String entered = idToStatsService.IdToName(patent.getEntered());
        String dept=idToStatsService.IdToDept(patent.getDept());
        String allauthor=idToStatsService.IdToAllauthor(patent.getAllAuthor());

        patent.setAllAuthor(allauthor);
        patent.setEntered(entered);
        patent.setDept(dept);

        return patent;
    }

    /**
     * 检查专利名称
     * @param patent_name
     * @return
     */
    @Override
    public boolean checkPatentName(String patent_name) {
        Patent one = super.getOne(Wrappers.lambdaQuery(Patent.class)
                .eq(Patent::getPatentName, patent_name));
        if(Objects.nonNull(one)){
            throw new BaseException("该专利名称已存在!");
        }
        return true;
    }


    /**
     * 院级专利审核通过
     * @param token
     * @param PaID
     * @return
     */
    @Override
    public Boolean collegeCheckPass(String token, String PaID) {
        Patent patent = query().eq("PatentID", PaID).one();
        if (patent == null) throw new BaseException("该专利编号有误!");

        String roleName = userInfoUtils.getCurrentUserInfo().getRoleName();
        // 目标状态根据角色确定
        String targetStatus = StatusCheckConstant.COLLEGE_CHECK_PEOPLE.equals(roleName)
                ? StatusCheckConstant.WAIT_SCHOOL_CHECK
                : StatusCheckConstant.CHECK_PASS;

        return checkAuditHelper.doPassAudit(
                patent,
                StatusCheckConstant.WAIT_COLLEGE_CHECK,
                targetStatus,
                roleName,
                "专利",
                patent::getPatentID,
                patent::getStatus,
                patent::setStatus,
                this::updatePatentByEntity
        );
    }

    /**
     * 院级专利审核退回
     * @param token
     * @param checkBackDTO
     * @return
     */
    @Override
    public Boolean collegeCheckBack(String token, CheckBackDTO checkBackDTO) {
        Patent patent = query().eq("PatentID", checkBackDTO.getID()).one();
        if (patent == null) throw new BaseException("该专利编号有误!");

        String roleName = userInfoUtils.getCurrentUserInfo().getRoleName();
        // 退回状态根据角色确定
        String backStatus = StatusCheckConstant.COLLEGE_CHECK_PEOPLE.equals(roleName)
                ? StatusCheckConstant.COLLEGE_CHECK_BACK
                : StatusCheckConstant.SCHOOL_CHECK_BACK;

        return checkAuditHelper.doBackAudit(
                patent,
                StatusCheckConstant.WAIT_COLLEGE_CHECK,
                backStatus,
                checkBackDTO.getReason(),
                "专利",
                patent::getPatentID,
                patent::getStatus,
                patent::setStatus,
                patent::setReason,
                this::updatePatentByEntity
        );
    }

    /**
     * 校级专利审核通过
     * @param token
     * @param PaID
     * @return
     */
    @Override
    public Boolean schoolCheckPass(String token, String PaID) {
        Patent patent = query().eq("PatentID", PaID).one();
        if (patent == null) throw new BaseException("该专利编号有误!");

        String currentStatus = patent.getStatus();
        if (!StatusCheckConstant.WAIT_SCHOOL_CHECK.equals(currentStatus)
                && !StatusCheckConstant.WAIT_COLLEGE_CHECK.equals(currentStatus)) {
            throw new BaseException("该专利状态不处于该环节!");
        }

        String roleName = userInfoUtils.getCurrentUserInfo().getRoleName();

        return checkAuditHelper.doPassAudit(
                patent,
                currentStatus,
                StatusCheckConstant.CHECK_PASS,
                roleName,
                "专利",
                patent::getPatentID,
                patent::getStatus,
                patent::setStatus,
                this::updatePatentByEntity
        );
    }

    /**
     * 校级专利审核退回
     * @param token
     * @param checkBackDTO
     * @return
     */
    @Override
    public Boolean schoolCheckBack(String token, CheckBackDTO checkBackDTO) {
        Patent patent = query().eq("PatentID", checkBackDTO.getID()).one();
        if (patent == null) throw new BaseException("该专利编号有误!");

        String currentStatus = patent.getStatus();
        if (!StatusCheckConstant.WAIT_SCHOOL_CHECK.equals(currentStatus)
                && !StatusCheckConstant.WAIT_COLLEGE_CHECK.equals(currentStatus)
                && !StatusCheckConstant.CHECK_PASS.equals(currentStatus)) {
            throw new BaseException("该专利状态不处于该环节!");
        }

        String roleName = userInfoUtils.getCurrentUserInfo().getRoleName();

        return checkAuditHelper.doBackAudit(
                patent,
                currentStatus,
                StatusCheckConstant.SCHOOL_CHECK_BACK,
                checkBackDTO.getReason(),
                "专利",
                patent::getPatentID,
                patent::getStatus,
                patent::setStatus,
                patent::setReason,
                this::updatePatentByEntity
        );
    }

    /**
     * 更新专利实体
     */
    private Boolean updatePatentByEntity(Patent patent) {
        return baseMapper.updateById(patent) == 1;
    }


    @Override
    public Boolean withdrawPatent(String patentID) {
        // 获取当前用户ID
        String userId = BaseContext.getCurrentId();
        // 验证用户是否存在
        User user = iUserService.getById(userId);
        if (Objects.isNull(user)) {
            throw new BaseException("用户不存在");
        }
        
        // 查询专利信息
        Patent patent = super.getOne(Wrappers.lambdaQuery(Patent.class).eq(Patent::getPatentID, patentID));
        if (Objects.isNull(patent)) {
            throw new BaseException("专利不存在");
        }
        
        // 检查专利状态是否为院级审核中
        if (!patent.getStatus().equals(StatusCheckConstant.WAIT_COLLEGE_CHECK)) {
            throw new BaseException("只有院级审核中的专利才能撤回");
        }
        
        // 将专利状态更新为草稿
        patent.setStatus(StatusCheckConstant.DRAFT);
        
        return baseMapper.updateById(patent) == 1;
    }
    
    @Override
    public Boolean ReCommitPatent(String patentID) {
        Patent patent = super.getOne(Wrappers.lambdaQuery(Patent.class).eq(Patent::getPatentID, patentID));
        if(Objects.isNull(patent)){
            throw new BaseException("专利编号有误!");
        }

        if(!patent.getStatus().equals("草稿") && !patent.getStatus().equals("被院级退回") && !patent.getStatus().equals("被校级退回")){
            throw new BaseException("该专利不适用于该阶段!");
        }
        //检查各项不可为空选项
        if (StrUtil.isEmpty(patent.getClassifi()) || StrUtil.isBlank(patent.getClassifi())){
            throw new BaseException("请输入统计分类!");
        }
        if (StrUtil.isEmpty(patent.getPatentName()) || StrUtil.isBlank(patent.getPatentName())){
            throw new BaseException("请输入专利名称!");
        }
        if (StrUtil.isEmpty(patent.getPatentNumber()) || StrUtil.isBlank(patent.getPatentNumber())){
            throw new BaseException("请输入专利号!");
        }
        if (StrUtil.isEmpty(patent.getPatentee()) || StrUtil.isBlank(patent.getPatentee())){
            throw new BaseException("请输入专利权人!");
        }
        if (StrUtil.isEmpty(patent.getPatentCate()) || StrUtil.isBlank(patent.getPatentCate())){
            throw new BaseException("请输入专利类型!");
        }

        patent.setStatus("待院级审核");
        patent.setReason("");
        
        // 检查量化分数是否填写
        Patent_Qualification qualification = iPatentQualificationSerivce.getOne(
                Wrappers.lambdaQuery(Patent_Qualification.class)
                        .eq(Patent_Qualification::getPatentID, patent.getPatentID())
        );
        if (Objects.isNull(qualification)) {
            throw new BaseException("请先填写专利的量化分数!");
        }
        
        // 检查作者列表是否填写
        List<Patentauthor> authorList = iPatentauthorService.list(
                Wrappers.lambdaQuery(Patentauthor.class)
                        .eq(Patentauthor::getPatentID, patent.getPatentID())
        );
        if (CollectionUtils.isEmpty(authorList)) {
            throw new BaseException("请先添加专利的作者信息!");
        }

        return baseMapper.updateById(patent)==1;
    }


    /**
     * 获取用户关联的专利
     * @param patentPageQuery
     * @return
     */
    @Override
    public CommonPage<PatentVO> userGetRelatePatent(PatentPageQuery patentPageQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);
        String role = user.getRole();

        // 创建MyBatis-Plus的Page对象
        Page<PatentVO> page = new Page<>(patentPageQuery.getPageNum(), patentPageQuery.getPageSize());
        IPage<PatentVO> patentIPage = null;
        // 根据角色执行不同查询
        if (role.equals(RoleConstant.ROLE_ADMIN_SCHOOL)) {
            patentIPage = patentMapper.schoolGetRelatePatentQuery(page, patentPageQuery, user);
        } else if (role.equals(RoleConstant.ROLE_ADMIN_COLLEGE)) {
            patentIPage = patentMapper.collegeGetRelatePatentQuery(page, patentPageQuery, user);
        } else {
            patentIPage = patentMapper.userGetRelatePatentQuery(page, patentPageQuery, user);
        }
        // 初始化量化分数
        float figure = 0;

        //查询专利关联的作者
        // 遍历记录，计算量化分数
        List<PatentVO> records = patentIPage.getRecords();
        for (PatentVO record : records) {
            if (record.getStatus().equals("审核通过")){
                figure += record.getScore();
            }

            String patentID = record.getPatentID();
            List<Patentauthor> patentauthors = iPatentauthorService.list(Wrappers.lambdaQuery(Patentauthor.class)
                    .eq(Patentauthor::getPatentID, patentID));
            //将作者以逗号分隔
            String allAuthor = patentauthors.stream()
                    .map(Patentauthor::getName)
                    .collect(Collectors.joining(","));
            record.setAllAuthor(allAuthor);
        }

        // 构造返回分页对象
        CommonPage<PatentVO> patentCommonPage = CommonPage.restPage(patentIPage);

        patentCommonPage.setFigure(figure);
        patentCommonPage.setList(records);

        return patentCommonPage;
    }

    @Override
    public CommonPage<Patent> export(PatentPageQuery patentPageQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);
        String role = user.getRole();

        Page<Patent> page = new Page<>(patentPageQuery.getPageNum(), patentPageQuery.getPageSize());
        IPage<Patent> patentIPage;

        if (RoleConstant.ROLE_ADMIN_SCHOOL.equals(role)) {
            patentIPage = patentMapper.schoolExportRelatePatentQuery(page, patentPageQuery, user);
        } else if (RoleConstant.ROLE_ADMIN_COLLEGE.equals(role)) {
            patentIPage = patentMapper.collegeExportRelatePatentQuery(page, patentPageQuery, user);
        } else {
            patentIPage = patentMapper.userExportRelatePatentQuery(page, patentPageQuery, user);
        }

        List<Patent> records = patentIPage.getRecords();
        float figure = 0;

        for (Patent record : records) {
            if (StatusCheckConstant.CHECK_PASS.equals(record.getStatus())) {
                figure += record.getScore();
            }

            String patentID = record.getPatentID();

            // 查询第一作者和共同第一作者
            List<Patentauthor> leadAuthors = iPatentauthorService.list(Wrappers.lambdaQuery(Patentauthor.class)
                    .eq(Patentauthor::getPatentID, patentID)
                    .in(Patentauthor::getAuthortype, Arrays.asList("第一作者", "共同第一作者")));
            record.setLeadAuthor(leadAuthors.stream().map(Patentauthor::getName).collect(Collectors.joining(",")));

            // 查询通讯作者
            List<Patentauthor> contactAuthors = iPatentauthorService.list(Wrappers.lambdaQuery(Patentauthor.class)
                    .eq(Patentauthor::getPatentID, patentID)
                    .eq(Patentauthor::getAuthortype, "通讯作者"));
            record.setCorrespondingAuthor(contactAuthors.stream().map(Patentauthor::getName).collect(Collectors.joining(",")));

            // 查询所有作者（用于显示完整作者列表）
            List<Patentauthor> allAuthors = iPatentauthorService.list(Wrappers.lambdaQuery(Patentauthor.class)
                    .eq(Patentauthor::getPatentID, patentID));
            record.setAllAuthor(allAuthors.stream().map(Patentauthor::getName).collect(Collectors.joining(",")));
        }


        CommonPage<Patent> commonPage = CommonPage.restPage(patentIPage);
        commonPage.setFigure(figure);
        commonPage.setList(records);

        return commonPage;
    }






}
